package org.mozhu.mboot.admin.maintain.i18n.service;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import org.mozhu.mboot.core.data.BaseService;
import org.mozhu.mboot.core.i18n.MessageChangeEvent;
import org.mozhu.mboot.core.i18n.MessageResourceLoader;
import org.mozhu.mboot.admin.maintain.i18n.entity.I18NResource;
import org.mozhu.mboot.admin.maintain.i18n.entity.LocaleType;
import org.mozhu.mboot.admin.maintain.i18n.repository.I18NResourceRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * @author mozhu
 */
@Transactional
@Service("i18nResourceService")
public class I18NResourceService extends BaseService<I18NResource, Long> implements MessageResourceLoader, ApplicationEventPublisherAware {
	private Logger logger = LoggerFactory.getLogger(getClass());

	protected ApplicationEventPublisher applicationEventPublisher;

	protected I18NResourceRepository getBaseRepository() {
		return (I18NResourceRepository) baseRepository;
	}

	@Override
	public Map<String, Map<Locale, String>> loadMessages() {
		Map<String, Map<Locale, String>> messages = Maps.newHashMap();
		List<I18NResource> resources = this.getBaseRepository().findAll();
		for (I18NResource i18nResource : resources) {
			String key = i18nResource.getKey();
			String message = i18nResource.getMessage();
			String localeString = i18nResource.getLocale();
			if (StringUtils.isBlank(key) || message == null || StringUtils.isBlank(localeString)) {
				continue;
			}
			try {
				Locale locale = LocaleUtils.toLocale(localeString);
				Map<Locale, String> localeMessages = messages.get(key);
				if (localeMessages == null) {
					localeMessages = Maps.newHashMap();
					messages.put(key, localeMessages);
				}
				localeMessages.put(locale, message);
			} catch (IllegalArgumentException e) {
				logger.error("Invalid format of locale[" + localeString + "]", e);
			}
		}
		return messages;
	}

	@Override
	public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
		this.applicationEventPublisher = applicationEventPublisher;
	}

	@Override
	public I18NResource save(I18NResource entity) {
		I18NResource i18nResource = super.save(entity);
		notifyChange(entity.getKey(), LocaleType.valueOf(entity.getLocale()).getLocale(), entity.getMessage());
		return i18nResource;
	}

	public void notifyChange(String key, Locale locale, String message) {
		applicationEventPublisher.publishEvent(new MessageChangeEvent(this, key, message, locale));
	}

}
